package it.unicam.ids.pvm.data.mysql;

import it.unicam.ids.pvm.data.DAOException;
import it.unicam.ids.pvm.data.ProdottoDAO;
import it.unicam.ids.pvm.distributore.Prodotto;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

/**
 * La classe rappresenta un'implementazione dell'interfaccia ProdottoDAO,
 * relativa al DBMS MySQL.
 * 
 * @author Luca Iachini, Valerio Iachini, Alessandro Cardenà
 * 
 */
public class MySQLProdottoDAO implements ProdottoDAO {
	final String sqlDelete = "DELETE FROM prodotto WHERE codice = ?";
	final String sqlInsert = "INSERT INTO prodotto (codice, descrizione, prezzo, promozione, ingredienti, valori_nutrizionali) VALUES (?,?,?,?,?,?)";
	final String sqlUpdate = "UPDATE prodotto SET codice =?, descrizione = ?, prezzo = ?, promozione=?, ingredienti = ?, valori_nutrizionali = ? WHERE codice = ?";
	final String sqlSelectAll = "SELECT codice, descrizione, prezzo, promozione, ingredienti, valori_nutrizionali FROM prodotto";
	final String sqlSelectProdotto = "SELECT * FROM prodotto WHERE codice = ?";
	final String sqlCanDelete = "SELECT COUNT(*) FROM casella WHERE prodotto = ?";

	@Override
	public void delete(Prodotto prodotto) throws DAOException {
		Connection conn = MySQLDAOFactory.createConnection();
		PreparedStatement ps = null;
		boolean error = false;
		try {
			ps = conn.prepareStatement(sqlDelete);
			ps.setString(1, prodotto.getCodice());
			ps.executeUpdate();
		} catch (SQLException e) {
			error = true;
		} finally {
			if (ps != null) {
				try {
					ps.close();
				} catch (SQLException e) {
					error = true;
				}
			}
			if (error)
				throw new DAOException(
						"Errore nella cancellazione del prodotto");
		}

	}

	@Override
	public Prodotto[] findAllProdotti() throws DAOException {
		Prodotto[] prodotti = null;
		PreparedStatement ps = null;
		ResultSet rs = null;
		boolean error = false;
		Connection conn = MySQLDAOFactory.createConnection();
		try {
			ps = conn.prepareStatement(sqlSelectAll);
			rs = ps.executeQuery();
			prodotti = new Prodotto[getRowCount(rs)];
			for (int i = 0; rs.next(); i++) {
				String codice = rs.getString("codice");
				String descrizione = rs.getString("descrizione");
				double prezzo = rs.getDouble("prezzo");
				double promozione = rs.getDouble("promozione");
				String ingredienti = rs.getString("ingredienti");
				String valoriNutrizionali = rs.getString("valori_nutrizionali");
				prodotti[i] = new Prodotto(codice, prezzo, descrizione);
				prodotti[i].setPromozine(promozione);
				prodotti[i].setIngredienti(ingredienti);
				prodotti[i].setValoriNutrizionali(valoriNutrizionali);
			}
		} catch (Exception e) {
			error = true;
		} finally {
			if (ps != null) {
				try {
					ps.close();
				} catch (SQLException e) {
					error = true;
				}
			}
			if (rs != null) {
				try {
					rs.close();
				} catch (SQLException e) {
					error = true;
				}
			}
			if (error)
				throw new DAOException(
						"Errore nel recupero dei dati riguardanti le caselle");
		}
		return prodotti;
	}

	@Override
	public Prodotto findByCodice(String codice) throws DAOException {
		Prodotto prodotto = null;
		PreparedStatement ps = null;
		ResultSet rs = null;
		boolean error = false;
		Connection conn = MySQLDAOFactory.createConnection();
		try {
			ps = conn.prepareStatement(sqlSelectProdotto);
			ps.setString(1, codice);
			rs = ps.executeQuery();
			if (rs.next()) {
				String descrizione = rs.getString("descrizione");
				double prezzo = rs.getDouble("prezzo");
				double promozione = rs.getDouble("promozione");
				String ingredienti = rs.getString("ingredienti");
				String valoriNutrizionali = rs.getString("valori_nutrizionali");
				prodotto = new Prodotto(codice, prezzo, descrizione);
				prodotto.setPromozine(promozione);
				prodotto.setIngredienti(ingredienti);
				prodotto.setValoriNutrizionali(valoriNutrizionali);
			}
		} catch (Exception e) {
			error = true;
		} finally {
			if (ps != null) {
				try {
					ps.close();
				} catch (SQLException e) {
					error = true;
				}
			}
			if (rs != null) {
				try {
					rs.close();
				} catch (SQLException e) {
					error = true;
				}
			}
			if (error)
				throw new DAOException(
						"Errore nel recupero dei dati riguardanti la casella : "
								+ codice);
		}
		return prodotto;
	}

	@Override
	public void insert(Prodotto prodotto) throws DAOException {
		Connection conn = MySQLDAOFactory.createConnection();
		PreparedStatement ps = null;
		boolean error = false;
		try {
			ps = conn.prepareStatement(sqlInsert);
			ps.setString(1, prodotto.getCodice());
			ps.setString(2, prodotto.getDescrizione());
			ps.setDouble(3, prodotto.getPrezzo());
			ps.setDouble(4, prodotto.getPromozione());
			ps.setString(5, prodotto.getIngredienti());
			ps.setString(6, prodotto.getValoriNutrizionali());
			ps.executeUpdate();
		} catch (SQLException e) {
			error = true;
		} finally {
			if (ps != null) {
				try {
					ps.close();
					
				} catch (SQLException e) {
					error = true;
				}
			}
			if (error)
				throw new DAOException(
						"Errore nell'inserimento del prodotto : " + prodotto);
		}

	}

	@Override
	public void update(Prodotto prodotto, String oldCodice) throws DAOException {
		Connection conn = MySQLDAOFactory.createConnection();
		PreparedStatement ps = null;
		boolean error = false;
		try {
			ps = conn.prepareStatement(sqlUpdate);
			ps.setString(1, prodotto.getCodice());
			ps.setString(2, prodotto.getDescrizione());
			ps.setDouble(3, prodotto.getPrezzo());
			ps.setDouble(4, prodotto.getPromozione());
			ps.setString(5, prodotto.getIngredienti());
			ps.setString(6, prodotto.getValoriNutrizionali());
			ps.setString(7, oldCodice);
			ps.executeUpdate();
		} catch (SQLException e) {
			error = true;
		} finally {
			if (ps != null) {
				try {
					ps.close();
				} catch (SQLException e) {
					error = true;
				}
			}
			if (error)
				throw new DAOException("Errore nell'aggiornamento del prodotto");
		}

	}

	@Override
	public boolean canDelete(String codice) throws DAOException {
		PreparedStatement ps = null;
		boolean error = false;
		int numeroAssociazioni = 0;
		ResultSet rs = null;
		Connection conn = MySQLDAOFactory.createConnection();
		try {
			ps = conn.prepareStatement(sqlCanDelete);
			ps.setString(1, codice);
			rs = ps.executeQuery();
			rs.next();
			numeroAssociazioni = rs.getInt(1);
		} catch (Exception e) {
			error = true;
		} finally {
			if (ps != null) {
				try {
					ps.close();
				} catch (SQLException e) {
					error = true;
				}
			}
			if (rs != null)
				try {
					rs.close();
				} catch (SQLException e) {
					error = true;
				}
			if (error)
				throw new DAOException(
						"Errore nella verifica per la cancellazione del prodotto");
		}
		return numeroAssociazioni == 1;
	}

	/**
	 * Il metodo restituisce il numero di righe della tabella relativa ai
	 * prodotti del database.
	 * 
	 * @param rs
	 *            risultato di una query.
	 * @return n numero delle righe.
	 * @throws SQLException
	 */

	private int getRowCount(ResultSet rs) throws SQLException {
		rs.last();
		int n = rs.getRow();
		rs.beforeFirst();
		return n;
	}

}
